package cn.edu.swu.miniwebsvr.handler;

import cn.edu.swu.miniwebsvr.core.Config;
import cn.edu.swu.miniwebsvr.core.Handler;
import cn.edu.swu.miniwebsvr.core.Parameter;
import java.io.*;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;

public class DefaultHandler implements Handler {

    @Override
    public void handle(Parameter request, OutputStream response) {
        // TODO: [222024321072031/黄璜]
        // 1. 获取请求路径（可能需要将 / 映射到 index.html）
        String url = request.getUrl();
        String sub = "/".equals(url) ? "index.html" : url.substring(1);
        // 2. 根据 Config.getWebRoot() 构建完整文件路径
        Path webRoot = Paths.get(Config.getInstance().getWebRoot()).toAbsolutePath();
        //System.out.println("[DEBUG]webRoot = " + webRoot);
        Path filePath = webRoot.resolve(sub).normalize();
        //Path filePath = Paths.get(Config.getInstance().getWebRoot(), request.getUrl().equals("/") ? "index.html" : request.getUrl().substring(1));

        //防止目录穿越，确保仍在webRoot里
        if (!filePath.startsWith(webRoot)){
            write404(response,url);
            flushQuietly(response);
            return;
        }

        try {
            if (Files.exists(filePath) && !Files.isDirectory(filePath)) {
                byte[] fileBytes = Files.readAllBytes(filePath);

                // TODO: [222024321072031/黄璜] 确定并设置正确的 Content-Type (例如 text/html, image/jpeg 等)
                //String contentType = Files.probeContentType(filePath) != null ? Files.probeContentType(filePath) : "application/octet-stream";
                String contentType = Files.probeContentType(filePath);
                if (contentType == null){
                    String name = filePath.getFileName().toString().toLowerCase();
                    if (name.endsWith(".html") || name.endsWith(".htm"))
                        contentType = "text/html; charset=UTF-8";
                    else if (name.endsWith(".css"))
                        contentType = "text/html; charset=UTF-8";
                    else if (name.endsWith(".js"))
                        contentType = "application/javascript; charset=UTF-8";
                    else if (name.endsWith(".png"))
                        contentType = "image/png";
                    else if (name.endsWith(".jpg") || name.endsWith(".jpeg"))
                    contentType = "image/jpeg";
                    else if (name.endsWith(".gif"))
                        contentType = "image/gif";
                    else if (name.endsWith(".svg"))
                        contentType = "image/svg+xml";
                    else contentType = "application/octet-stream";
                }

                // 写入 200 OK 响应头
                response.write(("HTTP/1.1 200 OK\r\n").getBytes());
                response.write(("Content-Type: " + contentType + "\r\n").getBytes());
                response.write(("Content-Length: " + fileBytes.length + "\r\n").getBytes());
                response.write(("\r\n").getBytes());

                // 写入文件内容
                response.write(fileBytes);
            } else {
                // 文件不存在或路径错误，返回 404
                write404(response, url);
            }

        } catch (IOException e) {
            // TODO: [222024321072031/黄璜] 文件读取异常，返回 500 Internal Server Error
            write500(response,e.getMessage());
        } finally {
            flushQuietly(response);
        }
    }
    private void write404(OutputStream response,String url){
        try {
            //String content = "<h1>404 Not Found</h1><p>The requested resource " + request.getUrl() + " was not found.</p>";
            String content = "<h1>404 Not Found</h1><p>The requested resource <code>" + url + "</code> was not found.</p>";
            response.write(("HTTP/1.1 404 Not Found\r\n").getBytes());
            response.write(("Content-Type: text/html; charset=UTF-8\r\n").getBytes());
            response.write(("Content-Length: " + content.getBytes().length + "\r\n").getBytes());
            response.write(("Connection: close\r\n").getBytes());
            response.write(("\r\n").getBytes());
            response.write(content.getBytes());


        }
        catch (IOException ignored){}
    }
    private void write500(OutputStream response,String msg){
        try {
            String content = "<h1>500 Internal Server Error</h1><pre>" + (msg == null ? "" : msg) + "</pre>";
            response.write(("HTTP/1.1 500 Internal Server Error\r\n").getBytes());
            response.write(("Content-Type: text/html; charset=UTF-8\r\n").getBytes());
            response.write(("Content-Length: " + content.getBytes().length + "\r\n").getBytes());
            response.write(("Connection: close\r\n").getBytes());
            response.write(("\r\n").getBytes());
            response.write(content.getBytes());

        }
        catch (IOException ignored){}
    }
    private void flushQuietly(OutputStream response){
        try {
            response.flush();
        }
        catch (IOException ignored){}
    }
}
